module PrismBreak {

    export class EventManager {

        private Events: Event[];
        private frameworkApp: PbApp;

        constructor(frameworkApp: PbApp) {
            this.Events = [];
            this.frameworkApp = frameworkApp;

        }


        public Subscribe(evType: EventType, callback: Function, priority?: number): string {

            var sub = new Subscription(callback, priority, this.frameworkApp.CreateRandomToken());

            var ev = this.GetEvent(evType);

            if (!ev) {
                ev = new Event(evType);
                this.Events.push(ev);
            }

            ev.AddSubscription(sub);

            return sub.Token;
        }

        public Unsubscribe(evType: EventType, token: string): void {

            var ev = this.GetEvent(evType);

            if (ev) {
                ev.RemoveSubscription(token);
            }
        }

        public Publish(evType: EventType, parameter?: any) {

            var ev = this.GetEvent(evType);

            if (ev) {
                if (this.EventHasSubscribers(ev)) {
                    this.PublishSubs(ev.Subscriptions, parameter);
                }

                else {
                    //TODO  warn missing subs
                    console.log("no subscribers");
                }
            }
            else {
                //TODO  warn missing event
                console.log("missing event");
            }
        }

        private PublishSubs(subs: Subscription[], parameter: any): void {

            for (var i = 0; i < subs.length; i++) {
                subs[i].Callback(parameter);
            }
        }

        private EventHasSubscribers(ev): boolean {

            if (ev && ev.Subscriptions.length) {
                return true;
            }

            else {
                return false;
            }
        }

        private GetEvent(type: EventType): Event {
            var event: Event = Enumerable.From(this.Events)
                .Where((item: Event) => {
                    return item.Name === type;
                }).SingleOrDefault(null);

            return event;

        }
    }
}